/*
* Copyright (c) 2020-2023 云南信和科技有限公司 All Rights Reserved.
* 当前软件由云南信和科技有限公司研制开发，未经公司正式同意，其他任何个人、团体不得使用复制修改.
* @author: yansheng
*/
package com.yuntu.micor.app.handler;


import com.yuntu.micor.app.constant.StringConstant;
import com.yuntu.micor.app.entity.ResponseCode;
import com.yuntu.micor.app.entity.ResponseData;
import com.yuntu.micor.app.exception.GlobalException;
import com.yuntu.micor.app.util.DataUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

import java.util.List;

/**
 * @author yansheng
 */
@Slf4j
public class BaseExceptionHandler {

    @ExceptionHandler(value = Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseData handleException(Exception e) {
        String message = DataUtils.containChinese(e.getMessage()) ? e.getMessage() : "系统内部异常";
        log.error(message, e);
        return ResponseData.fail(message, ResponseCode.SERVER_ERROR_CODE.getCode());
    }

    /**
     * 文件超大异常捕获
     */
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    @ResponseStatus(HttpStatus.PAYLOAD_TOO_LARGE)
    public ResponseData uploadException(MaxUploadSizeExceededException e)  {
        String message = DataUtils.containChinese(e.getMessage()) ? e.getMessage() : "上传文件大小超出限制!";
        log.error(message, e);
        return ResponseData.fail(message, HttpStatus.PAYLOAD_TOO_LARGE.value());
    }


    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResponseData validExceptionHandler(MethodArgumentNotValidException  e) {
        StringBuilder message = new StringBuilder();
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        for (FieldError error : fieldErrors) {
            message.append(error.getField()).append(error.getDefaultMessage()).append(",");
        }
        message = new StringBuilder(message.substring(0, message.length() - 1));
        return ResponseData.fail(message.toString(), ResponseCode.PARAM_ERROR_CODE.getCode());
    }

    @ExceptionHandler(value = GlobalException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseData handleXhException(GlobalException e) {
        log.error("系统错误", e);
        return ResponseData.fail(e.getMessage(), e.getCode());
    }

    /**
     * 统一处理请求参数校验(实体对象传参)
     *
     * @param e BindException
     * @return ResponseData
     */
    @ExceptionHandler(BindException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResponseData handleBindException(BindException e) {
        StringBuilder message = new StringBuilder();
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        for (FieldError error : fieldErrors) {
            message.append(error.getField()).append(error.getDefaultMessage()).append(StringConstant.COMMA);
        }
        message = new StringBuilder(message.substring(0, message.length() - 1));
        return ResponseData.fail(message.toString(),ResponseCode.PARAM_ERROR_CODE.getCode());
    }



    @ExceptionHandler(value = HttpMediaTypeNotSupportedException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseData handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) {
        String message = "该方法不支持" + StringUtils.substringBetween(e.getMessage(), StringConstant.SINGLE_QUOTE, StringConstant.SINGLE_QUOTE) + "媒体类型";
        log.error(message);
        return ResponseData.fail(message,ResponseCode.PARAM_ERROR_CODE.getCode());
    }

    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseData handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        String message = "该方法不支持" + StringUtils.substringBetween(e.getMessage(), StringConstant.SINGLE_QUOTE, StringConstant.SINGLE_QUOTE) + "请求方法";
        log.error(message);
        return ResponseData.fail(message,ResponseCode.PARAM_ERROR_CODE.getCode());
    }


    /**
     * 处理空指针的异常
     */
    @ExceptionHandler(value =NullPointerException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseData exceptionHandler( NullPointerException e){
        log.error("发生空指针异常！原因是:",e);
        return ResponseData.fail("发生空指针异常！",ResponseCode.SERVER_ERROR_CODE.getCode());
    }

    /**
     * 处理使用Assert.state断言
     */
    @ExceptionHandler(value =IllegalStateException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseData handlerIllegalStateException( IllegalStateException e){
        log.error("断言异常:",e);
        return ResponseData.fail("断言异常!",ResponseCode.SERVER_ERROR_CODE.getCode());
    }

    /**
     * 处理使用Assert.isTrue断言
     */
    @ExceptionHandler(value =IllegalArgumentException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseData handlerIllegalArgumentException( IllegalArgumentException e){
        log.error("断言异常:",e);
        return ResponseData.fail("断言异常！",ResponseCode.SERVER_ERROR_CODE.getCode());
    }

    /**
     * 必填参数缺失
     * @param e
     * @return
     */
    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResponseData handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
        String message = DataUtils.containChinese(e.getMessage()) ? e.getMessage() : "必填参数缺失";
        log.error(message, e);
        return ResponseData.fail(message, ResponseCode.PARAM_ERROR_CODE.getCode());
    }
}
